/**
在 Webpack 中，HTTP 压缩是一种优化技术，旨在通过压缩传输的文件内容来减少网络带宽的使用，提高网页加载速度。HTTP 压缩通常与服务器配置相关，能够有效地减小 JavaScript、CSS、HTML 等静态文件的体积，从而加快文件的传输速度。
  1. 什么是 HTTP 压缩？
  HTTP 压缩是指在客户端和服务器之间传输数据时，对传输的数据进行压缩，以减少数据的大小。常用的压缩算法包括 Gzip 和 Brotli。通过压缩，可以显著减少文件的传输时间和带宽消耗。

  2. HTTP 压缩的好处
  - 减少文件大小: 压缩可以减小文件的体积，降低网络带宽的使用。
  - 提高加载速度: 更小的文件意味着更快的下载速度，从而提高网页的加载速度和用户体验。
  - 节省服务器资源: 减少传输的数据量可以降低服务器的负载和带宽成本。

  3. 在 Webpack 中配置 HTTP 压缩
  虽然 Webpack 本身不直接处理 HTTP 压缩，但可以通过配置 Webpack 生成的文件与服务器的结合来实现。

   1. 使用 Webpack 生成压缩文件
  可以使用 `compression-webpack-plugin` 插件在构建时
  生成压缩文件。此插件会在构建过程中自动生成 Gzip 或 Brotli 压缩文件。

  安装插件：
  ```bash
  npm install --save-dev compression-webpack-plugin
  ```

  配置 Webpack：
  ```javascript
  const CompressionPlugin = require('compression-webpack-plugin');

  module.exports = {
      // 其他配置...
      plugins: [
          new CompressionPlugin({
              filename: '[path].gz[query]', // 输出文件名
              algorithm: 'gzip', // 使用 gzip 压缩
              test: /\.js$|\.css$|\.html$/, // 匹配文件类型
              threshold: 10240, // 只有大于 10KB 的文件才会被压缩
              minRatio: 0.8, // 压缩率
          }),
      ],
      mode: 'production', // 设置为生产模式
  };
  ```

   2. 服务器配置
  在服务器上（如 Nginx、Apache），需要配置 HTTP 压缩，以便在传输时对文件进行压缩。

  # Nginx 配置示例：
  ```nginx
  http {
      gzip on; # 启用 gzip 压缩
      gzip_types text/plain application/javascript text/css application/json; # 指定压缩的 MIME 类型
      gzip_min_length 1000; # 最小压缩文件大小
  }
  ```

  4. 注意事项
  - 浏览器支持: 确保目标浏览器支持所使用的压缩算法（如 Gzip 或 Brotli）。
  - 服务器性能: 启用压缩可能会增加服务器的 CPU 使用率，因此需要根据服务器性能进行评估。
  - 调试: 在启用压缩后，进行充分的测试以确保应用的功能没有受到影响。

  总结
  HTTP 压缩是一种有效的优化技术，可以显著提高 Webpack 构建应用的加载速度和性能。通过使用 `compression-webpack-plugin` 在构建时生成压缩文件，并在服务器上配置 HTTP 压缩，可以实现更快速的数据传输和更好的用户体验。希望这个总结对你理解 Webpack 中的 HTTP 压缩有所帮助！
 */
const path = require("path");
const glob = require("glob");
const TerserPlugin = require("terser-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// const CSSMinimizerPlugin = require("css-minimizer-webpack-plugin");
const { PurgeCSSPlugin } = require("purgecss-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const webpack = require("webpack");

/**
  [
    'src\\main.js',
    'src\\demo.js',
    'src\\abc.js',
    'src\\utils\\foo.js',
    'src\\utils\\bar.js',
    'src\\ts\\math.ts',
    'src\\router\\category.js',
    'src\\router\\about.js',
    'src\\react\\App.jsx',
    'src\\demo\\parse-lyric.js',
    'src\\demo\\math.js',
    'src\\css\\style.css'
  ]
 */
console.log(
  glob.sync(`${path.resolve(__dirname, "../src")}/**/*`, { nodir: true })
); // 获取所有文件

module.exports = {
  mode: "production",
  optimization: {
    chunkIds: "deterministic", // 生成文件名时使用确定的文件名
    runtimeChunk: {
      name: "runtime", // 将runtime相关的代码单独打包
    },
    splitChunks: {
      // 分包配置
      chunks: "all", // 对所有模块都进行分割
      minSize: 10, // 分割的模块最小为10kb
      // 自己对需要进行拆包的内容进行分包
      cacheGroups: {
        utils: {
          test: /utils/,
          filename: "js/[id]_utils.js",
        },
        vendors: {
          // /node_modules/
          // window上面 /\
          // mac上面 /
          test: /[\\/]node_modules[\\/]/,
          filename: "js/[id]_vendors.js",
        },
      },
    },
    minimize: true, // 是否使用压缩
    // 压缩配置
    minimizer: [
      // JS压缩的插件: TerserPlugin
      new TerserPlugin({
        extractComments: false, // 不将注释提取到单独的文件中
        terserOptions: {
          compress: {
            arguments: true, // 移除console.log
            unused: true, // 移除未使用的代码
          },
          mangle: true, // 压缩变量名
          // toplevel: true, // 移除未使用的变量
          keep_fnames: true, // 保留函数名
        },
      }),
      // CSS压缩的插件: CSSMinimizerPlugin
      // new CSSMinimizerPlugin({
      //   // parallel: true, // 开启多进程
      // }),
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
      chunkFilename: "css/[name]_chunk.css",
    }),
    // 对css进行treeshaking
    new PurgeCSSPlugin({
      paths: glob.sync(`${path.resolve(__dirname, "../src")}/**/*`, {
        nodir: true, // 不包括文件夹
      }),
      // safelist表示: 哪些类名不能被移除
      safelist: function () {
        return {
          standard: ["body"],
        };
      },
    }),
    new webpack.optimize.ModuleConcatenationPlugin(), // 作用域提升 Scope Hoisting
    new CompressionPlugin({
      test: /\.(js|css)$/, // 匹配文件类型
      algorithm: "gzip", // 使用 gzip 压缩
    }),
    new BundleAnalyzerPlugin(), // 打包分析
  ],
};
